<!DOCTYPE HTML>
<html lang="en">
<head>
<title>StreamDevice: Setup</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="favicon.ico" />
<link rel="stylesheet" type="text/css" href="stream.css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="Dirk Zimoch" />
</head>
<body>
<iframe src="nav.html" id="navleft"></iframe>
<h1>Setup</h1>

<a name="pre"></a>
<h2>1. Prerequisites</h2>
<p>
<em>StreamDevice</em> works with
<a href="https://epics.anl.gov/base/index.php">EPICS base</a>
versions from R3.14.6 on, tested up to 7.0.3.
It also works (with limitations) with older
<a href="https://epics.anl.gov/base/R3-13.php">R3.13</a> 
versions from R3.13.7 on.
How to use <em>StreamDevice</em> with EPICS R3.13 is described on a
<a href="epics3_13.html">separate page</a>.
<p>
Download and build the EPICS version of your choice first before continuing.
</p>
</p>
<h3>Fix required for base R3.14.8.2 and earlier on Windows</h3>
<p>
Up to release R3.14.8.2, a fix in EPICS base is required to build
<em>StreamDevice</em> on Windows (not cygwin).
Add the following line to <kbd>src/iocsh/iocsh.h</kbd>
and rebuild base.
</p>
<pre>
epicsShareFunc int epicsShareAPI iocshCmd(const char *command);
</pre>

<h3>Downloading <em>StreamDevice</em></h3>
The latest version of StreamDevice can be found on github:
<a href="https://github.com/paulscherrerinstitute/StreamDevice"
>https://github.com/paulscherrerinstitute/StreamDevice</a>.

Either download a <a
href="https://github.com/paulscherrerinstitute/StreamDevice/archive/master.zip
">zip file</a> or clone the git repo:
<pre>
git clone https://github.com/paulscherrerinstitute/StreamDevice.git
</pre>

<h3>Configuration</h3>
<p class="new">
<em>StreamDevice</em> now comes with a standard
<kbd>configure</kbd> directory.
<del>But it can still be built in an external <em>&lt;top&gt;</em>
directory as in previous versions.
It will automatically detect <em>&lt;top&gt;</em> locations
from the presence of <kbd>../configure</kbd> or <kbd>../config</kbd>
directories.</del> Using an upper level <kbd>../configure</kbd> is
no longer supported due to compatibility issues with <em>SynApps</em>.
</p>
<p class="new">
Edit the <kbd>configure/RELEASE</kbd> file to specify the install location
of EPICS base and of additional software modules or add a
<kbd>configure/RELEASE.local</kbd> file to overwrite, for example:
<pre>
EPICS_BASE=/home/epics/base-3.16.1
</pre>

<h4>Support for <em>asynDriver</em></h4>
<p>
You most probably want to have <em>asynDriver</em> support included, because
that is the standard way for <em>StreamDevice</em> to talk to hardware.
First get and install
<a href="https://www.aps.anl.gov/epics/modules/soft/asyn/"
><em>asynDriver</em></a> version 4-3 or higher before you build
<em>StreamDevice</em>.
I have tested <em>StreamDevice</em> with <em>asynDriver</em> versions up to 4-30.
Make sure that the <em>asyn</em> library can be found by adding the path to the
<em>&lt;top&gt;</em> directory of your <em>asyn</em> installation to the
<kbd>configure/RELEASE</kbd> file:
<pre>
ASYN=/home/epics/asyn4-30
</pre>

<h4>Support for <em>sCalcout</em> record</h4>
<p>
The <a 
href="https://htmlpreview.github.io/?https://raw.githubusercontent.com/epics-modules/calc/R3-6-1/documentation/sCalcoutRecord.html"
><em>sCalcout</em></a> record is part of <a
href="https://www.aps.anl.gov/BCDA/synApps"
><em>synApps</em></a>.
If <em>streamDevice</em> should be built with support for this record,
you have to install at least the <a
href="https://epics.anl.gov/bcda/synApps/calc/calc.html"
><em>calc</em> module</a> from <em>SynApps</em> first.
Add references to the <kbd>RELEASE</kbd> file as shown here:
<pre>
CALC=/home/epics/synApps/calc-R3-6-1
</pre>
<p>
Up to <em>calc</em> release R2-6 (<em>synApps</em> release R5_1),
the <em>sCalcout</em> record needs a fix.
(See separate <a href="scalcout.html"><em>scalcout</em> page</a>.)
And the <em>calc</em> module had dependencies on other <em>SynApps</em>
modules. Release R2-8 or newer is recommended.
</p>
<p>
Support for the <em>sCalcout</em> is optional. <em>StreamDevice</em> works
as well without <em>sCalcout</em> or <em>SynApps</em>.
</p>

<h4>Support for regular expression matching</h4>
<p>
If you want to enable regular expression matching, you need the <em>PCRE</em> package.
For most Linux systems, it is already installed.
In that case tell <em>StreamDevice</em> the locations of the
<em>PCRE</em> header file and library.
However, the pre-installed package can only by used for the host architecture.
Thus, add them not to <kbd>RELEASE</kbd> but to
<kbd>RELEASE.Common.linux-x86</kbd> (if linux-x86 is your EPICS_HOST_ARCH).
Be aware that different Linux distributions may locate the files in different
directories.
</p>
<pre>
PCRE_INCLUDE=/usr/include/pcre
PCRE_LIB=/usr/lib
</pre>
<p>
For 64 bit installations, the path to the library may be different:
</p>
<pre>
PCRE_INCLUDE=/usr/include/pcre
PCRE_LIB=/usr/lib64
</pre>
<p>
A pre-compiled Windows version of <em>PCRE</em> is available at
<a href="https://sourceforge.net/projects/gnuwin32/files/pcre/7.0/pcre-7.0.exe/download"
>sourceforge</a>
</p>
<p>
If you want to have <em>PCRE</em> support on platforms that don't support it natively,
e.g. vxWorks, it is probably the easiest to build <em>PCRE</em> as an EPICS module.
</p>
<p>
<h4>Building the <em>PCRE</em> package as an EPICS module</h4>
<p>
<ol>
<li>
Download the <em>PCRE</em> package from <a href="https://www.pcre.org">www.pcre.org</a>.
</li>
<li>
Extract the <em>PCRE</em> package in the <kbd>&lt;top&gt;</kbd> directory of
<em>StreamDevice</em> or create a separate <kbd>&lt;top&gt;</kbd> location using
<code>makeBaseApp.pl</code>.
</li>
<li>
Download this <a href="http://epics.web.psi.ch/software/streamdevice/pcre/Makefile"
>Makefile</a> and this
<a href="http://epics.web.psi.ch/software/streamdevice/pcre/fixforvxworks.pl"
>fixforvxworks.pl</a> script and save them to the extracted pcre directory.
</li>
<li>
Change into the pcre direcrory and run <code>perl fixforvxworks.pl</code>
</li>
<li>
Run <code>make</code> (or <code>gmake</code>)
</li>
</ol>
<p>
Define the location of the pcre <kbd>&lt;top&gt;</kbd> in the RELEASE file for <em>StreamDevice</em>.
</p>
<pre>
PCRE=/home/epics/pcre
</pre>
<p>
Regular expressions are optional. If you don't want them, you don't need this.
</p>

<a name="lib"></a>
<h2>2. Building <em>StreamDevice</em></h2>
<p>
Go to the <em>StreamDevice</em> directory
and run <code>make</code> (or <code>gmake</code>).
This will create and install the <em>stream</em> library and the
<kbd>stream.dbd</kbd> file and an example IOC application.
</p>

<p>
To use <em>StreamDevice</em>, your own application must be built with the
<em>stream</em> and <em>asyn</em> (and optionally <em>pcre</em>) libraries
and must load <kbd>asyn.dbd</kbd> and <kbd>stream.dbd</kbd>.
</p>
<p>
Include the following lines in your application <kbd>Makefile</kbd>:
</p>
<pre>
PROD_LIBS += stream
PROD_LIBS += asyn
PROD_LIBS += pcre
</pre>
<p>
Include the following lines in your <kbd>xxxAppInclude.dbd</kbd> file to use
<em>stream</em> and <em>asyn</em> with serial lines, IP sockets,
and vxi11 ("GPIB over ethernet") support.
</p>
<pre>
include "base.dbd"
include "stream.dbd"
include "asyn.dbd"
registrar(drvAsynIPPortRegisterCommands)
registrar(drvAsynSerialPortRegisterCommands)
registrar(vxi11RegisterCommands)
</pre>
<p>
You can find an example application in the <kbd>streamApp</kbd>
subdirectory.
</p>

<a name="sta"></a>
<h2>3. The Startup Script</h2>
<p>
<em>StreamDevice</em> is based on <a
href="protocol.html"><em>protocol files</em></a>.
To tell <em>StreamDevice</em> where to search for protocol files,
set the environment variable <code>STREAM_PROTOCOL_PATH</code> to a
list of directories to search.
On Unix and vxWorks systems, directories are separated by <code>:</code>,
on Windows systems by <code>;</code>.
The default value is <code>STREAM_PROTOCOL_PATH=.</code>,
i.e. the current directory.
</p>
<p>
Also configure the buses (in <em>asynDriver</em> terms: ports) you want
to use with <em>StreamDevice</em>.
You can give the buses any name you want, like <kbd>COM1</kbd> or
<kbd>socket</kbd>, but I recommend to use names related to the
connected device.
</p>
<h3>Example:</h3>
<p>
A device with serial communication (9600 baud, 8N1, no flow control) is
connected to <kbd>/dev/ttyS1</kbd>.
The name of the device shall be <tt>PS1</tt>.
Protocol files are either in the current working directory or in the
<kbd>../protocols</kbd> directory.
</p>
<p>
Then the startup script may look like this:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")

drvAsynSerialPortConfigure ("PS1","/dev/ttyS1")
asynSetOption ("PS1", 0, "baud", "9600")
asynSetOption ("PS1", 0, "bits", "8")
asynSetOption ("PS1", 0, "parity", "none")
asynSetOption ("PS1", 0, "stop", "1")
asynSetOption ("PS1", 0, "clocal", "Y")
asynSetOption ("PS1", 0, "crtscts", "N")
</pre>

<p>All above options are the defaults.
Thus their usage in optional in this case.
</p>
<p>
If the device uses hardware flow control, change the last two lines to:
</p>
<pre>
asynSetOption ("PS1", 0, "clocal", "N")
asynSetOption ("PS1", 0, "crtscts", "Y")
</pre>
<p>
Newer versions of <em>asyn</em> also support software flow control
(CTRL-S,CTRL-Q). If the device uses this, you may want to set:
</p>
<pre>
asynSetOption ("PS1", 0, "ixon", "Y")
asynSetOption ("PS1", 0, "ixany", "Y")
</pre>

<p>If the device was instead connected via telnet-style TCP/IP
at address 192.168.164.10 on port 23,
the startup script would contain:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")

drvAsynIPPortConfigure ("PS1", "192.168.164.10:23")
</pre>

<p>
With a VXI11 (GPIB via TCP/IP) connection, e.g. a
HP E2050A on IP address 192.168.164.10, it would look like this:
</p>
<pre>
epicsEnvSet ("STREAM_PROTOCOL_PATH", ".:../protocols")

vxi11Configure ("PS1","192.168.164.10",1,1000,"hpib")
</pre>


<a name="pro"></a>
<h2>4. The Protocol File</h2>
<p>
For each different type of hardware, create a protocol file
which defines protocols for all needed functions of the device.
The file name is arbitrary, but I recommend that it contains
the device type.
It must not contain spaces and should be short.
During <code>iocInit</code>, <em>streamDevice</em> loads and parses
the required protocol files.
If the files contain errors, they are printed on the IOC shell.
Put the protocol file in one of the directories listed in
<code>STREAM_PROTOCOL_PATH</code>.
</p>
<h3>Example:</h3>
<p>
<tt>PS1</tt> is an <em>ExamplePS</em> power supply.
It communicates via ASCII strings which are terminated by
&lt;carriage&nbsp;return&gt; &lt;line&nbsp;feed&gt; (ASCII codes 13, 10).
The output current can be set by sending a string like
<code>"CURRENT 5.13"</code>.
When asked with the string <code>"CURRENT?"</code>, the device returns
the last set value in a string like <code>"CURRENT 5.13 A"</code>.
</p>
<p>
Normally, an analog output record should write its value to the device.
But during startup, the record should be initialized from the the device.
The protocol file <kbd>ExamplePS.proto</kbd> defines the protocols
<code>getCurrent</code> and <code>setCurrent</code>.
</p>
<pre>
Terminator = CR LF;

getCurent {
        out "CURRENT?";
        in "CURRENT %f A";
    }

setCurrent {
    out "CURRENT %.2f";
    @init {
        getCurent;
    }
}
</pre>

<a name="reload"></a>
<h3>Reloading the Protocol File</h3>
<p>
During development, the protocol files might change frequently.
To prevent restarting the IOC all the time, it is possible to reload
the protocol file of one or all records with the shell function
<code>streamReload("<var>record</var>")</code>.
If <code>"<var>record</var>"</code> is not given
<span class="new">or empty</span>, all records using
<em>StreamDevice</em> reload their protocols.
<span class="new">In EPICS 3.14 or higher,
<code><var>record</var></code> can be a glob pattern.</span>
</p>
<p>
Furthermore, the <code>streamReloadSub</code> function can be used
with a subroutine record to reload all protocols.
</p>
<p>
Reloading the protocol file aborts currently running protocols.
This might set <code>SEVR=INVALID</code> and <code>STAT=UDF</code>.
If a record can't reload its protocol file (e.g. because of a syntax
error), it stays <code>INVALID</code>/<code>UDF</code> until a valid
protocol is loaded.
</p>

<p>
<span class="new">Reloading triggers an <code>@init</code>
<a href="protocol.html#except">handler</a>.</span>
See the <a href="protocol.html">next chapter</a> for protocol files in depth.
</p>

<a name="debug"></a>
<h2>5. Debug and Error Messages</h2>
<p>
Generation of debug and error messages is controlled with two shell variables,
<code>streamDebug</code> and <code>streamError</code>.
Setting those variables to 1 (actually to any number but 0) enables the
messages.
Per default debug messages are switched off and error messages are switched on.
Errors occuring while loading protocol files are always shown.
</p>
<p>
Warning: Enabling debug messages can create a lot of output!
At the moment, there is no way to set filters on debug or error messages.
</p>
<p>
Debug output can be redirected to a file with the command
<code>streamSetLogfile("<var>filename</var>")</code>.
When called without a filename, debug output is directed back
to the console.
</p>

<h3>Example (vxWorks):</h3>
<pre>
streamError=1
streamDebug=1
streamSetLogfile("logfile.txt")
</pre>

<h3>Example (iocsh):</h3>
<pre>
var streamError 1
var streamDebug 1
streamSetLogfile("logfile.txt")
</pre>

<a name="rec"></a>
<h2>6. Configuring the Records</h2>
<p>
To tell a record to use <em>StreamDevice</em>, set its <code>DTYP</code> field to
<code>"stream"</code>.
</p>
<p>
The <code>INP</code> or <code>OUT</code> link has the form
<code>"@<var>filename&nbsp;protocol</var>[(<var>arg1</var>,<var>arg2</var>,...)]&nbsp;</var>bus</var>&nbsp;[<var>address</var>&nbsp;[<var>parameters</var>]]"</code>.
</p>
<p>
(Elements in <code>[]</code> are optional. Do not type the <code>[]</code>).
</p>
<p>
Here, <code><var>filename</var></code> is the name of the protocol file and
<code><var>protocol</var></code> is the name of a protocol defined in this file.
(See the <a href="protocol.html">next chapter</a>.)
</p>
<p>
If the protocol requires <a href="protocol.html#argvar">arguments</a>,
specify them enclosed in parentheses:
<code><var>protocol</var>(<var>arg1,arg2,...</var>)</code>.
<span class="new">Spaces in the argument list are now allowed.
The first space before and after an argument is ignored. Further spaces are
considered part of the argument.</span>
</p>
<p>
The communication channel is specified with <code><var>bus</var></code>
(aka <em>asynDriver</em> "port") and <code><var>addr</var></code>.
If the bus does not have addresses, <code><var>addr</var></code> may be skipped.
Optional <code><var>parameters</var></code> are passed to the bus driver.
(At the moment, no bus driver supports parameters.)
</p>

<h3>Example:</h3>
<p>
Create an input record to read and an output record to set the current of <tt>PS1</tt>.
Use protocols <em>getCurrent</em> and <em>setCurrent</em> from file <em>ExamplePS.proto</em>.
The bus is called <em>PS1</em> like the device.
</p>

<pre>
record (ai, "PS1:I-get")
{
    field (DESC, "Read current of PS1")
    <b>field (DTYP, "stream")</b>
    <b>field (INP,  "@ExamplePS.proto getCurrent PS1")</b>
    field (EGU,  "A")
    field (PREC, "2")
    field (LOPR, "0")
    field (HOPR, "60")
    field (PINI, "YES")
    field (SCAN, "10 second")
}
record (ao, "PS1:I-set")
{
    field (DESC, "Set current of PS1")
    <b>field (DTYP, "stream")</b>
    <b>field (OUT,  "@ExamplePS.proto setCurrent PS1")</b>
    field (EGU,  "A")
    field (PREC, "2")
    field (DRVL, "0")
    field (DRVH, "60")
    field (LOPR, "0")
    field (HOPR, "60")
}
</pre>

<footer>
<a href="protocol.html">Next: Protocol Files</a>
Dirk Zimoch, 2018
</footer>
</body>
</html>
